home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Hardware / BetaScan / BetaScanDev / TestSrc / ScannerTest.c < prev    next >
C/C++ Source or Header  |  1999-01-23  |  18KB  |  603 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #include <exec/types.h>
  6. #include <proto/icon.h>
  7.  
  8. #include <MakeILBM.h>
  9. #include <Scanner_protos.h>
  10. #include <Scanner.h>
  11.  
  12. static struct ScannerOptions option;
  13.  
  14. static char*  unitName;
  15. static int    unitNum = 2;
  16.  
  17. static int    color;
  18. static int    speed;
  19. static fixed  fx0,fy0,fx1,fy1;
  20. static int    resolution;
  21. static int    brightness;
  22. static int    contrast;
  23. static int    shadow;
  24. static int    highlight;
  25. static int    midtone;
  26. static int    halftonePattern;
  27. static int    exposureTime;   
  28. static int    gamma;
  29. static int    compress;
  30. static char*  outputFile;
  31.  
  32. static char* sodType[] = {"Boolean","Integer","Fixed","String","Button",NULL};
  33. static char* sodUnit[] = {"No unit","Pixel","Bit","mm","DPI","Percent","µs",NULL};
  34. static char* cmdOptionString[ID_NUMBER_OF_OPTIONS] = 
  35. {
  36.   "",
  37.   "color",
  38.   "top left x",
  39.   "top left y",
  40.   "bottom right x",
  41.   "bottom right y",
  42.   "resolution",
  43.   "halftone pattern",
  44.   "brightness",
  45.   "contrast",
  46.   "gamma",
  47.   "shadow",
  48.   "highlight",
  49.   "threshold",
  50.   "time",
  51.   "ADF",
  52.   "speed"
  53. };
  54.  
  55. static struct OptionValue parameterValue[ID_NUMBER_OF_OPTIONS];
  56.  
  57. void  usage(void);
  58. void  showOptions(struct ScannerOptions* option);
  59. struct OptionDescriptor* descriptor(OptionId id);
  60. short readToolTypes(char **array,struct ScannerOptions* option);
  61. BOOL  toolValue(char** array,char* matchStr,struct OptionDescriptor* descr,int* val);
  62.  
  63. /**************************************************************************/
  64.  
  65. /**********************           M A I N           ***********************/
  66.  
  67. /**************************************************************************/
  68. int testStart(char **toolTypes)
  69. {
  70.   BYTE   status;
  71.   // char** toolTypes;
  72.   int    i;
  73.   char*  str;
  74.   
  75.   if( FindToolType(toolTypes,"help") )
  76.   {
  77.     usage();
  78.     
  79.     return 0;
  80.   }
  81.  
  82.   if( !(unitName = FindToolType(toolTypes,"device")) )
  83.     unitName = "scsi.device";
  84.   if( str = FindToolType(toolTypes,"unit") )
  85.     unitNum = strtol(str,NULL,10);
  86.  
  87.   memset(&option,0,sizeof(struct ScannerOptions));
  88.   openScanner(unitName,unitNum,&option,&status);
  89.  
  90.   if( FindToolType(toolTypes,"options") )
  91.   {
  92.     if( status )
  93.       puts("No scanner available.\n");
  94.     else
  95.     {
  96.       showOptions(&option);
  97.       closeScanner();
  98.     }
  99.     
  100.     return status;
  101.   }
  102.  
  103.   if( status == 0)
  104.   {
  105.     struct ScanInformation inform;
  106.     struct OptionValue     value[2];
  107.    
  108.     // value[1].sp_optionID = ID_NONE;
  109.     for( i = 0 ; i < option.so_optionNum ; i++ )
  110.     {
  111.       value[0].sp_optionID = option.so_descriptor[i].od_optionID;
  112.       value[0].sp_flags = CONTROL_GET;
  113.       controlOption(value,&status);
  114.       
  115.       if( !(value[0].sp_flags & CONTROL_INVALID) )
  116.       {
  117.         switch( option.so_descriptor[i].od_optionID )
  118.         {
  119.           case ID_SCANMODE:
  120.             color = value[0].sp_value;
  121.             break;
  122.           case ID_TL_X:             /* upper left corner of scan area     */
  123.             fx0 = DOUBLE_FIX(25.0); // value[0].sp_value;
  124.             break;
  125.           case ID_TL_Y:             /* upper left corner of scan area     */
  126.             fy0 = DOUBLE_FIX(50.0); // value[0].sp_value;
  127.             break;
  128.           case ID_BR_X:             /* bottom right corner of scan area   */
  129.             fx1 = DOUBLE_FIX(75.0); // value[0].sp_value;
  130.             break;
  131.           case ID_BR_Y:             /* bottom right corner of scan area   */
  132.             fy1 = DOUBLE_FIX(100.0);// value[0].sp_value;
  133.             break;
  134.           case ID_RESOLUTION:       /* scan resolution (combined x and y) */
  135.             resolution = value[0].sp_value;
  136.             break;
  137.           case ID_HALFTONEPATTERN:
  138.             halftonePattern = value[0].sp_value;
  139.             break;
  140.           case ID_BRIGHTNESS:
  141.             brightness = value[0].sp_value;
  142.             break;
  143.           case ID_CONTRAST:
  144.             contrast = value[0].sp_value;
  145.             break;
  146.           case ID_ANALOGGAMMA:
  147.             gamma = value[0].sp_value;
  148.             break;
  149.           case ID_BLACKLEVEL:  /* some times called shadow           */
  150.             shadow = value[0].sp_value;
  151.             break;
  152.           case ID_WHITELEVEL:  /* some times called highlight        */
  153.             highlight = value[0].sp_value;
  154.             break;
  155.           case ID_THRESHOLD:
  156.             midtone = value[0].sp_value;
  157.             break;
  158.           case ID_EXPOSURETIME:
  159.             exposureTime = value[0].sp_value;
  160.             break;
  161.           default:
  162.             break;
  163.         }
  164.       }
  165.     }
  166.     
  167.     if( status = readToolTypes(toolTypes,&option) )
  168.     {
  169.       usage();
  170.       closeScanner();
  171.       return status;
  172.     }
  173.  
  174.     parameterValue[ID_SCANMODE-1].sp_optionID = ID_SCANMODE;
  175.     parameterValue[ID_SCANMODE-1].sp_value = color;
  176.     parameterValue[ID_SCANMODE-1].sp_flags = CONTROL_SET;
  177.     controlOption(¶meterValue[ID_SCANMODE-1],&status);
  178.     
  179.     parameterValue[ID_SPEED-1].sp_optionID = ID_SPEED;
  180.     parameterValue[ID_SPEED-1].sp_value = speed;
  181.     parameterValue[ID_SPEED-1].sp_flags = CONTROL_SET;
  182.     controlOption(¶meterValue[ID_SPEED-1],&status);
  183.     
  184.     parameterValue[ID_TL_X-1].sp_optionID = ID_TL_X;
  185.     parameterValue[ID_TL_X-1].sp_value = fx0;
  186.     parameterValue[ID_TL_X-1].sp_flags = CONTROL_SET;
  187.     controlOption(¶meterValue[ID_TL_X-1],&status);
  188.     
  189.     parameterValue[ID_TL_Y-1].sp_optionID = ID_TL_Y;
  190.     parameterValue[ID_TL_Y-1].sp_value = fy0;
  191.     parameterValue[ID_TL_Y-1].sp_flags = CONTROL_SET;
  192.     controlOption(¶meterValue[ID_TL_Y-1],&status);
  193.     
  194.     parameterValue[ID_BR_X-1].sp_optionID = ID_BR_X;
  195.     parameterValue[ID_BR_X-1].sp_value = fx1;
  196.     parameterValue[ID_BR_X-1].sp_flags = CONTROL_SET;
  197.     controlOption(¶meterValue[ID_BR_X-1],&status);
  198.     
  199.     parameterValue[ID_BR_Y-1].sp_optionID = ID_BR_Y;
  200.     parameterValue[ID_BR_Y-1].sp_value = fy1;
  201.     parameterValue[ID_BR_Y-1].sp_flags = CONTROL_SET;
  202.     controlOption(¶meterValue[ID_BR_Y-1],&status);
  203.     
  204.     parameterValue[ID_RESOLUTION-1].sp_optionID = ID_RESOLUTION;
  205.     parameterValue[ID_RESOLUTION-1].sp_value = resolution;
  206.     parameterValue[ID_RESOLUTION-1].sp_flags = CONTROL_SET;
  207.     controlOption(¶meterValue[ID_RESOLUTION-1],&status);
  208.     
  209.     parameterValue[ID_HALFTONEPATTERN-1].sp_optionID = ID_HALFTONEPATTERN;
  210.     parameterValue[ID_HALFTONEPATTERN-1].sp_value = halftonePattern;
  211.     parameterValue[ID_HALFTONEPATTERN-1].sp_flags = CONTROL_SET;
  212.     controlOption(¶meterValue[ID_HALFTONEPATTERN-1],&status);
  213.     
  214.     parameterValue[ID_BRIGHTNESS-1].sp_optionID = ID_BRIGHTNESS;
  215.     parameterValue[ID_BRIGHTNESS-1].sp_value = brightness;
  216.     parameterValue[ID_BRIGHTNESS-1].sp_flags = CONTROL_SET;
  217.     controlOption(¶meterValue[ID_BRIGHTNESS-1],&status);
  218.     
  219.     parameterValue[ID_CONTRAST-1].sp_optionID = ID_CONTRAST;
  220.     parameterValue[ID_CONTRAST-1].sp_value = contrast;
  221.     parameterValue[ID_CONTRAST-1].sp_flags = CONTROL_SET;
  222.     controlOption(¶meterValue[ID_CONTRAST-1],&status);
  223.     
  224.     parameterValue[ID_ANALOGGAMMA-1].sp_optionID = ID_ANALOGGAMMA;
  225.     parameterValue[ID_ANALOGGAMMA-1].sp_value = gamma;
  226.     parameterValue[ID_ANALOGGAMMA-1].sp_flags = CONTROL_SET;
  227.     controlOption(¶meterValue[ID_ANALOGGAMMA-1],&status);
  228.     
  229.     parameterValue[ID_BLACKLEVEL-1].sp_optionID = ID_BLACKLEVEL;
  230.     parameterValue[ID_BLACKLEVEL-1].sp_value = shadow;
  231.     parameterValue[ID_BLACKLEVEL-1].sp_flags = CONTROL_SET;
  232.     controlOption(¶meterValue[ID_BLACKLEVEL-1],&status);
  233.     
  234.     parameterValue[ID_WHITELEVEL-1].sp_optionID = ID_WHITELEVEL;
  235.     parameterValue[ID_WHITELEVEL-1].sp_value = highlight;
  236.     parameterValue[ID_WHITELEVEL-1].sp_flags = CONTROL_SET;
  237.     controlOption(¶meterValue[ID_WHITELEVEL-1],&status);
  238.     
  239.     parameterValue[ID_THRESHOLD-1].sp_optionID = ID_THRESHOLD;
  240.     parameterValue[ID_THRESHOLD-1].sp_value = midtone;
  241.     parameterValue[ID_THRESHOLD-1].sp_flags = CONTROL_SET;
  242.     controlOption(¶meterValue[ID_THRESHOLD-1],&status);
  243.     
  244.     parameterValue[ID_EXPOSURETIME-1].sp_optionID = ID_EXPOSURETIME;
  245.     parameterValue[ID_EXPOSURETIME-1].sp_value = exposureTime;
  246.     parameterValue[ID_EXPOSURETIME-1].sp_flags = CONTROL_SET;
  247.     controlOption(¶meterValue[ID_EXPOSURETIME-1],&status);
  248.     
  249.     // parameterValue[ID_NUMBER_OF_OPTIONS-1].sp_optionID = ID_NONE;
  250.     
  251.     // controlOption(parameterValue,&status);
  252.    
  253.     if( status == 0 )
  254.     {
  255.       startScanning(&inform,&status);
  256.      
  257.       if( status == 0 )
  258.       {
  259.         struct ILBMFile *fh;
  260.         struct ScanLine line;
  261.         
  262.         if( (line.sl_data = malloc(inform.sv_bytesPerLine)) && (fh = openILBM(outputFile,compress,&inform)) )
  263.         {
  264.           line.sl_color = 0;
  265.           
  266.           while( status == 0 )
  267.           {
  268.             readScanLine(&line,&status);
  269.             if( status == 0 )
  270.               writeILBM(fh,&line);
  271.           }
  272.           
  273.           if( status == SCAN_STATUS_EOF )
  274.           {
  275.             closeILBM(fh,0);
  276.             status = 0;
  277.           }
  278.           else
  279.             closeILBM(fh,1);
  280.         }
  281.  
  282.         stopScanning();
  283.         
  284.         if( line.sl_data )
  285.           free(line.sl_data);
  286.       }
  287.     }
  288.  
  289.     closeScanner();
  290.   }
  291.  
  292.   return status;
  293. }
  294.  
  295. void usage(void)
  296. {
  297.   puts("\nUsage: Scanner [options]\n");
  298.   puts("where options are:\n");
  299.   
  300.   puts("help                print this usage\n");
  301.  
  302.   puts("options             show scanner options\n");
  303.  
  304.   puts("device=<name>       default is: device=scsi.device\n");
  305.     
  306.   puts("unit=n              default is: unit=2\n");
  307.  
  308.   puts("debug=n             set debug level to n");
  309.   puts("                    default is: debug=0\n");
  310.  
  311.   puts("color=<color name>  default is driver default\n");
  312.  
  313.   puts("speed=s             default is driver default\n");
  314.  
  315.   puts("frame=x0,y0,x1,y1   upper left and lower right corner in mm");
  316.   puts("                    default is: frame=25,50,75,100\n");
  317.  
  318.   puts("resolution=r        resolution in dpi");
  319.   puts("                    default is driver default\n");
  320.  
  321.   puts("brightness=b        default is driver default\n");
  322.  
  323.   puts("contrast=c          default is driver default\n");
  324.  
  325.   puts("shadow=s            default is driver default\n");
  326.  
  327.   puts("highlight=h         default is driver default\n");
  328.  
  329.   puts("threshold=m         default is driver default\n");
  330.  
  331.   puts("pattern=p           default is driver default\n");
  332.  
  333.   puts("time=t              exposure time");
  334.   puts("                    default is driver default\n");
  335.  
  336.   puts("gamma=g             default is: gamma=1.0\n");
  337.  
  338.   puts("compress=on|off     default is: compress=on\n");
  339.  
  340.   puts("file=<name>         default is: file=ram:scanner.ilbm\n");
  341.  
  342.  
  343.   puts("Example: scanner\n");
  344.   puts("         scanner color=Gray frame=0,0,10,10 compress=off file=dh0:test.ilbm\n");
  345. }
  346.  
  347. void showOptions(struct ScannerOptions* option)
  348. {
  349.   struct OptionValue value[2];
  350.   int  i;
  351.   BYTE status;
  352.   
  353.   printf("\nScanner: %s %s \n\n",option->so_scannerVendor,option->so_scannerModel);
  354.  
  355.   printf("Driver version %d.%d\n\n",option->so_driverVersion,option->so_driverRevision);
  356.  
  357.   printf("Document width:  %5.1f mm\n",option->so_docWidth);
  358.   printf("Document height: %5.1f mm\n\n",option->so_docHeight);
  359.   
  360.   // value[1].sp_optionID = ID_NONE;
  361.   for( i = 0 ; i < option->so_optionNum ; i++ )
  362.   {
  363.     value[0].sp_optionID = option->so_descriptor[i].od_optionID;
  364.     value[0].sp_flags = CONTROL_GET;
  365.     controlOption(value,&status);
  366.       
  367.     printf("%s:\n",cmdOptionString[option->so_descriptor[i].od_optionID]);
  368.     printf("  type:  %s\n",sodType[option->so_descriptor[i].od_valueType]);
  369.     printf("  unit:  %s\n",sodUnit[option->so_descriptor[i].od_valueUnit]);
  370.  
  371.     switch( option->so_descriptor[i].od_constraintType )
  372.           {
  373.       case CONSTRAINT_NONE:
  374.         break;
  375.       case CONSTRAINT_STRING_LIST:
  376.         {
  377.           char** p;
  378.                    
  379.           p = option->so_descriptor[i].od_constraint.stringList;
  380.           
  381.           printf("  values: %s\n",*p);
  382.           p++;         
  383.           while( *p )
  384.           {
  385.             printf("          %s\n",*p);
  386.             p++;
  387.           }
  388.  
  389.           printf("  default=%s\n",option->so_descriptor[i].od_constraint.stringList[value[0].sp_value]);
  390.         }
  391.         break;
  392.       case CONSTRAINT_WORD_LIST:
  393.         {
  394.           int x;
  395.  
  396.           printf("  list: ");  //(%d) : ",option->so_descriptor[i].od_numberList[0]);
  397.                 for(x = 1; x <= option->so_descriptor[i].od_constraint.numberList[0]; x++)
  398.           {
  399.             if( option->so_descriptor[i].od_valueType == TYPE_INT )
  400.               printf(" %d, ",option->so_descriptor[i].od_constraint.numberList[x]);
  401.             else if( option->so_descriptor[i].od_valueType == TYPE_FIXED )
  402.               printf(" %1.1f, ",FIX_DOUBLE(option->so_descriptor[i].od_constraint.numberList[x]));
  403.           }
  404.           printf("\n");
  405.  
  406.           if( option->so_descriptor[i].od_valueType == TYPE_INT )
  407.             printf("  default=%d\n",value[0].sp_value);
  408.           else if( option->so_descriptor[i].od_valueType == TYPE_FIXED )
  409.             printf("  default=%1.1f\n",FIX_DOUBLE(value[0].sp_value));
  410.         }
  411.               break;
  412.       case CONSTRAINT_RANGE:
  413.         if( option->so_descriptor[i].od_valueType == TYPE_INT )
  414.           printf("  range: %d .. %d with steps: %d \n",
  415.                   option->so_descriptor[i].od_constraint.numberRange->min,
  416.                   option->so_descriptor[i].od_constraint.numberRange->max,
  417.                   option->so_descriptor[i].od_constraint.numberRange->quant
  418.                 );
  419.         else if( option->so_descriptor[i].od_valueType == TYPE_FIXED )
  420.           printf("  range: %1.1f .. %1.1f with steps: %1.1f \n",
  421.                  FIX_DOUBLE(option->so_descriptor[i].od_constraint.numberRange->min),
  422.                  FIX_DOUBLE(option->so_descriptor[i].od_constraint.numberRange->max),
  423.                  (option->so_descriptor[i].od_constraint.numberRange->quant?FIX_DOUBLE(option->so_descriptor[i].od_constraint.numberRange->quant):0.1)
  424.                 );
  425.  
  426.         if( option->so_descriptor[i].od_valueType == TYPE_INT )
  427.           printf("  default=%d\n",value[0].sp_value);
  428.         else if( option->so_descriptor[i].od_valueType == TYPE_FIXED )
  429.           printf("  default=%1.1f\n",FIX_DOUBLE(value[0].sp_value));
  430.  
  431.               break;
  432.     }
  433.     printf("\n");
  434.   }
  435. }
  436.  
  437. short readToolTypes(char **array,struct ScannerOptions* option)
  438. {
  439.   char* str;
  440.     
  441.   // Get frame coordinates
  442.   if( str = FindToolType(array,"frame") )
  443.   {
  444.     fx0 = DOUBLE_FIX(strtod(str,&str));
  445.     if( *(str++) != ',' )
  446.       return 2;
  447.     fy0 = DOUBLE_FIX(strtod(str,&str));
  448.     if( *(str++) != ',' )
  449.       return 2;
  450.     fx1 = DOUBLE_FIX(strtod(str,&str));
  451.     if( *(str++) != ',' )
  452.       return 2;
  453.     fy1 = DOUBLE_FIX(strtod(str,&str));
  454.     if( (*str != ' ') && (*str != 0) )
  455.       return 1;
  456.   }
  457.  
  458.   if( !toolValue(array,"color",descriptor(ID_SCANMODE),&color) )
  459.     return 2;
  460.  
  461.   if( !toolValue(array,"speed",descriptor(ID_SPEED),&speed) )
  462.     return 2;
  463.  
  464.   if( !toolValue(array,"resolution",descriptor(ID_RESOLUTION),&resolution) )
  465.     return 3;
  466.  
  467.   if( !toolValue(array,"brightness",descriptor(ID_BRIGHTNESS),&brightness) )
  468.     return 4;
  469.  
  470.   if( !toolValue(array,"contrast",descriptor(ID_CONTRAST),&contrast) )
  471.     return 5;
  472.  
  473.   if( !toolValue(array,"shadow",descriptor(ID_BLACKLEVEL),&shadow) )
  474.     return 6;
  475.  
  476.   if( !toolValue(array,"highlight",descriptor(ID_WHITELEVEL),&highlight) )
  477.     return 7;
  478.  
  479.   if( !toolValue(array,"pattern",descriptor(ID_HALFTONEPATTERN),&halftonePattern) )
  480.     return 8;
  481.  
  482.   if( !toolValue(array,"time",descriptor(ID_EXPOSURETIME),&exposureTime) )
  483.     return 9;
  484.  
  485.   if( !toolValue(array,"midtone",descriptor(ID_THRESHOLD),&midtone) )
  486.     return 10;
  487.  
  488.   if( !toolValue(array,"gamma",descriptor(ID_ANALOGGAMMA),&gamma) )
  489.     return 11;
  490.  
  491.   if( str = FindToolType(array,"compress") )
  492.   {
  493.     if( MatchToolValue(str,"on") )
  494.       compress = 1;
  495.     else if( MatchToolValue(str,"off") )
  496.       compress = 0;
  497.     else
  498.       return 12;
  499.   }
  500.   else
  501.     compress = 1;
  502.  
  503.   if( !(outputFile = FindToolType(array,"file")) )
  504.     outputFile = "ram:scanner.ilbm";
  505.     
  506.   return 0;
  507. }
  508.  
  509. struct OptionDescriptor* descriptor(OptionId id)
  510. {
  511.   int i;
  512.   
  513.   for( i = 0 ; i < option.so_optionNum ; i++ )
  514.   {
  515.     if( id == option.so_descriptor[i].od_optionID )
  516.       return &option.so_descriptor[i];
  517.   }
  518.  
  519.   return NULL;
  520. }
  521.  
  522. BOOL toolValue(char** array,char* matchStr,struct OptionDescriptor* descr,int* val)
  523. {
  524.   char* toolStr;
  525.   
  526.   if( descr == NULL )
  527.     return TRUE;      
  528.   
  529.   toolStr = FindToolType(array,matchStr);
  530.   
  531.   if( toolStr == NULL )
  532.     return TRUE;
  533.     
  534.   switch( descr->od_valueType )
  535.   {
  536.     case TYPE_BOOL:
  537.       if( MatchToolValue(toolStr,"on") )
  538.       {
  539.         *val = 1;
  540.         return TRUE;
  541.       }
  542.       else if( MatchToolValue(toolStr,"off") )
  543.       {
  544.         *val = 0;
  545.         return TRUE;
  546.       }
  547.       else
  548.         return FALSE;
  549.     case TYPE_INT:
  550.     case TYPE_FIXED:
  551.       if( descr->od_valueType == TYPE_INT )
  552.         *val = strtol(toolStr,NULL,10);
  553.       else
  554.         *val = DOUBLE_FIX(strtod(toolStr,NULL));
  555.         
  556.       switch( descr->od_constraintType )
  557.       {
  558.         case CONSTRAINT_RANGE:
  559.           if( *val < descr->od_constraint.numberRange->min )
  560.             *val = descr->od_constraint.numberRange->min;
  561.           else if( *val > descr->od_constraint.numberRange->max )
  562.             *val = descr->od_constraint.numberRange->max;
  563.           else if( descr->od_constraint.numberRange->quant > 0 )
  564.           {
  565.             int n = descr->od_constraint.numberRange->min;
  566.             
  567.             while( *val > n + descr->od_constraint.numberRange->quant )
  568.               n += descr->od_constraint.numberRange->quant;
  569.             *val = n;
  570.           }
  571.           return TRUE;
  572.         case CONSTRAINT_WORD_LIST:
  573.           {
  574.             int i;
  575.             
  576.             for( i = 1 ; i < descr->od_constraint.numberList[0] ; i++ )
  577.             {
  578.               if( *val < descr->od_constraint.numberList[i+1] )
  579.               {
  580.                 *val = descr->od_constraint.numberList[i];
  581.                 return TRUE;
  582.               }
  583.             }
  584.             *val = descr->od_constraint.numberList[i+1];
  585.             return TRUE;
  586.           }
  587.         default:
  588.           return FALSE;
  589.       }
  590.       
  591.       break;
  592.     case TYPE_STRING:
  593.       *val = 0;
  594.       
  595.       while( descr->od_constraint.stringList[*val] && strcmpi(toolStr,descr->od_constraint.stringList[*val]) )
  596.         (*val)++;
  597.       if( descr->od_constraint.stringList[*val] )
  598.         return TRUE;
  599.       else
  600.         return FALSE;
  601.   }
  602. }
  603.